<template>
  <div class="app-container">
    <div class="layout-container">
      <!-- 左侧患者信息区域 -->
      <div class="left-panel">
        <div class="stats-section">
          <div class="stat-item">
            <div class="stat-number">{{ stats.appointments  }}</div>
            <div class="stat-label">预约</div>
          </div>
          <div class="stat-item">
            <div class="stat-number">{{ stats.completed  }}</div>
            <div class="stat-label">已完成</div>
          </div>
          <el-button type="primary" class="add-patient-btn" size="small" @click="showAddDialog">
            <el-icon><Plus /></el-icon>
            添加患者 
          </el-button>
        </div>
 
        <div class="date-indicator" v-if="selectedDate">
          当前显示：{{ formatDate(selectedDate) }} 的预约（共{{ filteredPatients.length  }}条）
          <el-button type="text" @click="clearDateFilter">清除筛选</el-button>
        </div>
 
        <div class="patient-table">
          <div class="table-header">
            <div class="header-cell" v-for="col in columns" :key="col.prop"  :style="{width: col.width}"> 
              {{ col.label  }}
            </div>
          </div>
          <div class="table-body">
            <div class="table-row" v-for="(patient, index) in displayPatients" :key="index">
              <div class="table-cell" v-for="col in columns" :key="col.prop"  :style="{width: col.width}"> 
                <template v-if="col.prop  === 'status'">
                  <el-tag :type="patient.status  === '未就诊' ? 'warning' : 'success'" size="small">
                    {{ patient.status  }}
                  </el-tag>
                </template>
                <template v-else-if="col.prop  === 'gender'">
                  <el-tag :type="patient.gender  === '男' ? 'primary' : 'danger'" size="small">
                    {{ patient.gender  }}
                  </el-tag>
                </template>
                <template v-else-if="col.prop  === 'actions'">
                  <el-button type="danger" size="small" circle @click="cancelAppointment(patient)">
                    <el-icon><Close /></el-icon>
                  </el-button>
                </template>
                <template v-else>
                  {{ patient[col.prop] }}
                </template>
              </div>
            </div>
          </div>
        </div>
 
        <div class="pagination">
          <el-button type="text" :disabled="currentPage === 1" @click="prevPage">
            上一页 
          </el-button>
          <span class="page-info">{{ currentPage }}/{{ totalPages }}</span>
          <el-button type="text" :disabled="currentPage === totalPages" @click="nextPage">
            下一页 
          </el-button>
        </div>
      </div>
 
      <!-- 右侧日历和图表区域 -->
      <div class="right-panel">
        <div class="calendar-section">
          <div class="section-title">请选择日期</div>
          <div class="year-month-selector">
            <el-select v-model="selectedYear" size="small" class="year-select" @change="updateCalendar">
              <el-option v-for="year in years" :key="year" :label="`${year}年`" :value="year" />
            </el-select>
            <el-select v-model="selectedMonth" size="small" class="month-select" @change="updateCalendar">
              <el-option v-for="month in months" :key="month.value"  :label="`${month.value}  月`" :value="month.value"  />
            </el-select>
          </div>
 
          <div class="weekdays">
            <div class="weekday" v-for="day in weekdays" :key="day">{{ day }}</div>
          </div>
 
          <div class="calendar-grid">
            <div 
              v-for="(day, index) in calendarDays"
              :key="index"
              :class="['calendar-day', {
                'other-month': !day.isCurrentMonth, 
                'today': day.isToday, 
                'selected': day.isSelected, 
                'has-appointment': day.hasAppointment  
              }]"
              @click="selectDay(day)"
            >
              <div class="day-number">{{ day.day  }}</div>
              <div class="appointment-dot" v-if="day.hasAppointment"></div> 
              <div class="appointment-count" v-if="day.appointmentCount  > 0">
                {{ day.appointmentCount  }}
              </div>
            </div>
          </div>
        </div>
 
        <div class="chart-section">
          <div class="section-title">每周预约统计</div>
          <div class="visit-type-toggle">
            <el-radio-group v-model="visitType" size="small">
              <el-radio-button label="全部" />
              <el-radio-button label="初诊" />
              <el-radio-button label="复诊" />
            </el-radio-group>
          </div>
          <div class="chart-container" ref="chartContainer"></div>
          <div class="chart-summary">
            <div class="summary-item">
              <div class="summary-value">{{ weeklyTotal }}</div>
              <div class="summary-label">本周总预约</div>
            </div>
            <div class="summary-item">
              <div class="summary-value">{{ weeklyMax }}</div>
              <div class="summary-label">峰值预约日</div>
            </div>
          </div>
        </div>
      </div>
    </div>
 
    <!-- 添加患者对话框 -->
    <el-dialog v-model="dialogVisible" title="添加患者" width="500px">
      <el-form :model="newPatient" label-width="80px" :rules="formRules" ref="patientForm">
        <el-form-item label="患者姓名" prop="name">
          <el-input v-model="newPatient.name"  placeholder="请输入患者姓名" />
        </el-form-item>
        <el-form-item label="性别" prop="gender">
          <el-radio-group v-model="newPatient.gender"> 
            <el-radio label="男" />
            <el-radio label="女" />
          </el-radio-group>
        </el-form-item>
        <el-form-item label="手机号" prop="phone">
          <el-input v-model="newPatient.phone"  placeholder="请输入手机号" />
        </el-form-item>
        <el-form-item label="预约时间" prop="appointmentTime">
          <el-date-picker 
            v-model="newPatient.appointmentTime" 
            type="datetime"
            placeholder="选择预约时间"
            value-format="YYYY-MM-DD HH:mm:ss"
          />
        </el-form-item>
        <el-form-item label="就诊类型" prop="visitType">
          <el-select v-model="newPatient.visitType"  placeholder="请选择就诊类型">
            <el-option label="初诊" value="初诊" />
            <el-option label="复诊" value="复诊" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="addPatient">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>
 
<script setup>
import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { Plus, Close } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRegistrationStore } from '@/stores/registrationStore'
 
// 使用Pinia store 
const registrationStore = useRegistrationStore()
 
// 统计数据 
const stats = computed(() => ({
  appointments: registrationStore.registrations.length, 
  completed: registrationStore.registrations.filter(r  => r.status  === '已完成').length 
}))
 
// 表格列配置 
const columns = ref([
  { prop: 'order', label: '排序', width: '60px' },
  { prop: 'name', label: '患者姓名', width: '100px' },
  { prop: 'gender', label: '性别', width: '80px' },
  { prop: 'phone', label: '手机号', width: '120px' },
  { prop: 'registerTime', label: '挂号时间', width: '160px' },
  { prop: 'status', label: '就诊状态', width: '100px' },
  { prop: 'actions', label: '操作', width: '80px' }
])
 
// 分页相关 
const currentPage = ref(1)
const pageSize = ref(10)
const totalPages = computed(() => Math.ceil(displayPatients.value.length  / pageSize.value)) 
 
// 显示的患者数据（考虑分页和筛选）
const displayPatients = computed(() => {
  const start = (currentPage.value  - 1) * pageSize.value  
  const end = start + pageSize.value  
  return filteredPatients.value.slice(start,  end)
})
 
// 日历相关 
const selectedYear = ref(new Date().getFullYear())
const selectedMonth = ref(new Date().getMonth() + 1)
const years = ref(Array.from({length:  10}, (_, i) => new Date().getFullYear() - 5 + i))
const months = ref(Array.from({length:  12}, (_, i) => ({label: `${i+1}月`, value: i+1})))
const weekdays = ref(['一', '二', '三', '四', '五', '六', '日'])
const selectedDate = ref(null)
const filteredPatients = ref([])
 
// 图表相关 
const chartContainer = ref(null)
let chartInstance = null 
const visitType = ref('全部')
const weeklyTotal = ref(0)
const weeklyMax = ref(0)
 
// 计算日历天数 
const calendarDays = computed(() => {
  const days = []
  const date = new Date(selectedYear.value,  selectedMonth.value  - 1, 1)
  const firstDay = (date.getDay()  + 6) % 7 // 调整为周一开始 
  const lastDay = new Date(selectedYear.value,  selectedMonth.value,  0).getDate()
  
  // 获取当前月份的预约数据 
  const monthRegistrations = registrationStore.registrations.filter(r  => {
    const regDate = new Date(r.registerTime) 
    return regDate.getFullYear()  === selectedYear.value  &&
           regDate.getMonth()  + 1 === selectedMonth.value  
  })
  
  // 上个月的最后几天 
  const prevMonthLastDay = new Date(selectedYear.value,  selectedMonth.value  - 1, 0).getDate()
  for (let i = firstDay - 1; i >= 0; i--) {
    const day = prevMonthLastDay - i 
    const dayDate = new Date(selectedYear.value,  selectedMonth.value  - 2, day)
    
    // 检查这一天是否有预约 
    const dayAppointments = monthRegistrations.filter(r  => {
      const regDate = new Date(r.registerTime) 
      return regDate.getDate()  === day && regDate.getMonth()  + 1 === selectedMonth.value  - 1 
    })
    
    days.push({ 
      day: day,
      isCurrentMonth: false,
      isToday: false,
      isSelected: false,
      hasAppointment: dayAppointments.length  > 0,
      appointmentCount: dayAppointments.length, 
      date: dayDate 
    })
  }
  
  // 当前月的天数 
  const today = new Date()
  for (let i = 1; i <= lastDay; i++) {
    const dayDate = new Date(selectedYear.value,  selectedMonth.value  - 1, i)
    const isToday = dayDate.getDate()  === today.getDate()  &&
                   dayDate.getMonth()  === today.getMonth()  &&
                   dayDate.getFullYear()  === today.getFullYear() 
    
    // 检查这一天是否有预约 
    const dayAppointments = monthRegistrations.filter(r  => {
      const regDate = new Date(r.registerTime) 
      return regDate.getDate()  === i 
    })
    
    days.push({ 
      day: i,
      isCurrentMonth: true,
      isToday: isToday,
      isSelected: selectedDate.value  && dayDate.toDateString()  === selectedDate.value.toDateString(), 
      hasAppointment: dayAppointments.length  > 0,
      appointmentCount: dayAppointments.length, 
      date: dayDate 
    })
  }
  
  // 下个月的前几天 
  const daysNeeded = 42 - days.length  // 6行7列共42天 
  for (let i = 1; i <= daysNeeded; i++) {
    const dayDate = new Date(selectedYear.value,  selectedMonth.value,  i)
    
    // 检查这一天是否有预约 
    const dayAppointments = monthRegistrations.filter(r  => {
      const regDate = new Date(r.registerTime) 
      return regDate.getDate()  === i && regDate.getMonth()  + 1 === selectedMonth.value  + 1 
    })
    
    days.push({ 
      day: i,
      isCurrentMonth: false,
      isToday: false,
      isSelected: false,
      hasAppointment: dayAppointments.length  > 0,
      appointmentCount: dayAppointments.length, 
      date: dayDate 
    })
  }
  
  return days 
})
 
// 对话框相关 
const dialogVisible = ref(false)
const patientForm = ref(null)
const newPatient = ref({
  name: '',
  gender: '男',
  phone: '',
  appointmentTime: '',
  visitType: '初诊'
})
 
// 表单验证规则 
const formRules = {
  name: [{ required: true, message: '请输入患者姓名', trigger: 'blur' }],
  phone: [
    { required: true, message: '请输入手机号', trigger: 'blur' },
    { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
  ],
  appointmentTime: [{ required: true, message: '请选择预约时间', trigger: 'change' }],
  visitType: [{ required: true, message: '请选择就诊类型', trigger: 'change' }]
}
 
// 方法 
const showAddDialog = () => {
  dialogVisible.value  = true 
}
 
const addPatient = async () => {
  try {
    await patientForm.value.validate() 
    
    await registrationStore.addRegistration({ 
      ...newPatient.value, 
      order: registrationStore.registrations.length  + 1,
      status: '未就诊',
      registerTime: newPatient.value.appointmentTime  
    })
    
    ElMessage.success(' 添加成功')
    dialogVisible.value  = false 
    newPatient.value  = {
      name: '',
      gender: '男',
      phone: '',
      appointmentTime: '',
      visitType: '初诊'
    }
    
    // 更新日历和图表 
    updateCalendar()
    initChart()
  } catch (error) {
    if (error !== 'validate') {
      console.error(' 添加患者失败:', error)
      ElMessage.error(' 添加失败')
    }
  }
}
 
const cancelAppointment = (patient) => {
  ElMessageBox.confirm( 
    `确定要删除患者 ${patient.name}  的预约吗？`,
    '删除确认',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
  .then(async () => {
    try {
      await registrationStore.deleteRegistration(patient.id) 
      ElMessage.success(' 删除成功')
      
      // 更新日历和图表 
      updateCalendar()
      initChart()
    } catch (error) {
      console.error(' 删除预约失败:', error)
      ElMessage.error(' 删除失败')
    }
  })
  .catch(() => {
    // 用户点击了取消 
  })
}
 
const prevPage = () => {
  if (currentPage.value  > 1) {
    currentPage.value-- 
  }
}
 
const nextPage = () => {
  if (currentPage.value  < totalPages.value)  {
    currentPage.value++ 
  }
}
 
const selectDay = (day) => {
  if (day.isCurrentMonth)  {
    selectedDate.value  = day.date  
    filteredPatients.value  = registrationStore.registrations.filter(patient  => {
      const patientDate = new Date(patient.registerTime) 
      return (
        patientDate.getFullYear()  === day.date.getFullYear()  &&
        patientDate.getMonth()  === day.date.getMonth()  &&
        patientDate.getDate()  === day.date.getDate() 
      )
    })
    currentPage.value  = 1 
  }
}
 
const clearDateFilter = () => {
  selectedDate.value  = null 
  filteredPatients.value  = [...registrationStore.registrations] 
  currentPage.value  = 1 
}
 
const updateCalendar = () => {
  // 强制更新计算属性 
  filteredPatients.value  = [...filteredPatients.value] 
}
 
const formatDate = (date) => {
  if (!date) return ''
  const d = new Date(date)
  const year = d.getFullYear() 
  const month = String(d.getMonth()  + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2,  '0')
  const weekday = ['日', '一', '二', '三', '四', '五', '六'][d.getDay()]
  return `${year}年${month}月${day}日 周${weekday}`
}
 
// 初始化图表 
const initChart = () => {
  if (!chartContainer.value)  return 
  
  if (chartInstance) {
    chartInstance.dispose() 
  }
  
  chartInstance = echarts.init(chartContainer.value) 
  
  // 根据筛选条件获取数据 
  let filteredData = registrationStore.registrations  
  if (visitType.value  === '初诊') {
    filteredData = filteredData.filter(r  => r.visitType  === '初诊')
  } else if (visitType.value  === '复诊') {
    filteredData = filteredData.filter(r  => r.visitType  === '复诊')
  }
  
  // 按星期分组 
  const weekData = [0, 0, 0, 0, 0, 0, 0] // 周一到周日 
  filteredData.forEach(r  => {
    const day = new Date(r.registerTime).getDay()  // 0-6, 0是周日 
    const index = day === 0 ? 6 : day - 1 // 转换为周一到周日的索引 
    weekData[index]++
  })
  
  // 更新统计数据 
  weeklyTotal.value  = weekData.reduce((a,  b) => a + b, 0)
  weeklyMax.value  = Math.max(...weekData) 
  
  const option = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      },
      formatter: params => {
        return `${params[0].axisValue}<br/>预约量: <span style="font-weight:bold;color:#409EFF">${params[0].value}</span>`
      }
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '15%',
      containLabel: true 
    },
    xAxis: {
      type: 'category',
      data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
      axisLine: {
        lineStyle: {
          color: '#999'
        }
      },
      axisTick: {
        alignWithLabel: true 
      },
      axisLabel: {
        interval: 0,
        color: '#606266'
      }
    },
    yAxis: {
      type: 'value',
      axisLine: {
        show: false 
      },
      axisTick: {
        show: false 
      },
      splitLine: {
        lineStyle: {
          type: 'dashed',
          color: '#e6e6e6'
        }
      }
    },
    series: [
      {
        name: '预约量',
        type: 'bar',
        barWidth: '40%',
        data: weekData,
        itemStyle: {
          borderRadius: [4, 4, 0, 0],
          color: new echarts.graphic.LinearGradient(0,  0, 0, 1, [
            { offset: 0, color: '#5B8FF9' },
            { offset: 1, color: '#36CBCB' }
          ])
        },
        label: {
          show: true,
          position: 'top',
          color: '#606266',
          formatter: (params) => {
            return params.value  > 0 ? params.value  : ''
          }
        },
        emphasis: {
          itemStyle: {
            color: new echarts.graphic.LinearGradient(0,  0, 0, 1, [
              { offset: 0, color: '#3A7CEB' },
              { offset: 1, color: '#2AA9A9' }
            ])
          }
        },
        animationDuration: 1500,
        animationEasing: 'cubicOut'
      }
    ]
  }
  
  chartInstance.setOption(option) 
  window.addEventListener('resize',  () => chartInstance.resize()) 
}
 
// 监听就诊类型变化 
watch(visitType, () => {
  if (chartInstance) {
    initChart()
  }
})
 
// 监听store数据变化 
watch(() => registrationStore.registrations,  () => {
  filteredPatients.value  = [...registrationStore.registrations] 
  if (chartInstance) {
    initChart()
  }
}, { deep: true })
 
// 生命周期 
onMounted(async () => {
  // 初始化时加载数据 
  await registrationStore.fetchRegistrations() 
  filteredPatients.value  = [...registrationStore.registrations] 
  
  await nextTick()
  initChart()
})
</script>
 
<style scoped>
.app-container {
  width: 100%;
  height: 100%;
  background-color: #f5f7fa;
  padding: 20px;
  box-sizing: border-box;
}
 
.layout-container {
  display: flex;
  height: calc(100% - 40px);
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  overflow: hidden;
}
 
.left-panel {
  width: 55%;
  padding: 20px;
  border-right: 1px solid #ebeef5;
  display: flex;
  flex-direction: column;
}
 
.right-panel {
  width: 45%;
  padding: 20px;
  display: flex;
  flex-direction: column;
}
 
.stats-section {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
  gap: 30px;
}
 
.stat-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
 
.stat-number {
  font-size: 24px;
  font-weight: bold;
  color: #409EFF;
}
 
.stat-label {
  font-size: 14px;
  color: #909399;
}
 
.add-patient-btn {
  margin-left: auto;
}
 
.date-indicator {
  padding: 8px 15px;
  background-color: #f0f7ff;
  border-radius: 4px;
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: #409EFF;
  font-size: 14px;
}
 
.patient-table {
  flex: 1;
  overflow-y: auto;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}
 
.table-header {
  display: flex;
  background-color: #f5f7fa;
  font-weight: bold;
  color: #606266;
  border-bottom: 1px solid #ebeef5;
}
 
.header-cell {
  padding: 12px 10px;
  text-align: center;
}
 
.table-body {
  overflow-y: auto;
  max-height: calc(100vh - 280px);
}
 
.table-row {
  display: flex;
  border-bottom: 1px solid #ebeef5;
}
 
.table-row:hover {
  background-color: #f5f7fa;
}
 
.table-cell {
  padding: 12px 10px;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
 
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 15px;
  gap: 20px;
}
 
.page-info {
  color: #606266;
  font-size: 14px;
}
 
.calendar-section {
  margin-bottom: 20px;
}
 
.section-title {
  font-size: 16px;
  color: #606266;
  margin-bottom: 15px;
  font-weight: bold;
}
 
.year-month-selector {
  display: flex;
  gap: 10px;
  margin-bottom: 15px;
}
 
.year-select, .month-select {
  width: 100px;
}
 
.weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-weight: bold;
  color: #606266;
  margin-bottom: 10px;
}
 
.weekday {
  padding: 5px;
}
 
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}
 
.calendar-day {
  height: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  border: 1px solid transparent;
}
 
.calendar-day:hover {
  background-color: #f5f7fa;
}
 
.calendar-day.other-month  {
  color: #c0c4cc;
}
 
.calendar-day.today  {
  font-weight: bold;
  color: #409EFF;
}
 
.calendar-day.selected  {
  background-color: #ecf5ff;
  border: 1px solid #409EFF;
}
 
.calendar-day.has-appointment  {
  background-color: #f0f7ff;
}
 
.day-number {
  font-size: 14px;
  margin-bottom: 2px;
}
 
.appointment-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: #f56c6c;
  margin-bottom: 2px;
}
 
.appointment-count {
  position: absolute;
  top: 2px;
  right: 2px;
  background-color: #f56c6c;
  color: white;
  border-radius: 50%;
  width: 16px;
  height: 16px;
  font-size: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}
 
.chart-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
}
 
.visit-type-toggle {
  margin-bottom: 15px;
  display: flex;
  justify-content: center;
}
 
.chart-container {
  flex: 1;
  min-height: 300px;
}
 
.chart-summary {
  display: flex;
  justify-content: space-around;
  margin-top: 15px;
  padding: 15px;
  background-color: #f5f7fa;
  border-radius: 8px;
}
 
.summary-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}
 
.summary-value {
  font-size: 24px;
  font-weight: bold;
  color: #409EFF;
}
 
.summary-label {
  font-size: 14px;
  color: #909399;
  margin-top: 5px;
}
 
/* 响应式调整 */
@media (max-width: 1200px) {
  .layout-container {
    flex-direction: column;
  }
  
  .left-panel, .right-panel {
    width: 100%;
  }
  
  .left-panel {
    border-right: none;
    border-bottom: 1px solid #ebeef5;
  }
  
  .calendar-day {
    height: 40px;
  }
  
  .chart-summary {
    flex-direction: column;
    gap: 15px;
  }
}
</style>